import graphUtil from "pages/mxgraph/graphUtil";
import { shapeApi } from 'src/api/shape/shapeApi';
import { uniqueArr } from 'src/util/common';
import { getStyleObj, getStyleStr } from 'src/util/common';
import { LifelineUtil } from "./behaviors/SequenceDiagram/LifelineUtil";
import { GraphShapeUtil } from "./GraphShapeUtil";
import ResizeUtil from './resizeUtil';

export default {
  /**
   * 刷新画布
   * @param {*} graph
   * @param {*} option
   */
  freshGraph(graph:Graph, option: any = { all: true }) {
    if (!graph.visible) return;
    try {
      console.log('fresh');

      graph.inFresh = true;

      const { all, diagramId, diagramIds, modelId, modelIds, shapeId, shapeIds } = option;
      const diagramShape = graph.diagramNode.umlDiagramFrame;//// 刷新画布时可能此画布已经被删除了，所以要从diagramNode重新取一遍，如果没有则return
      if (!diagramShape) return;
      console.time('fresh-time');
      if (all) {
        this.updateDiagramName(graph);

        const flatShapes = this.getFlatShapes(diagramShape);
        const cells = graph.model.cells;
        const modelCells = Object.keys(cells).map(key => cells[key]);
       
        const needReOrderParent:Set<string> = new Set();//// 子元素需要重新排序的元素
        const needReflowParent:Set<UmlShape> = new Set();//// 需要刷新的元素
        let needResizeSeqDiagram = false;
        flatShapes.forEach(shape => {

          //// 如果没有对应的cell则创建cell
          if (!cells[shape.id]) {
            graphUtil.addCellByUmlShape(graph, shape, {}, shape.deep);
            
            //// 新创建的元素需要重新排序
            if (shape.owner){
              needReOrderParent.add(shape.owner.id);
              //// needReOrderParent[shape.owner.id] = true;
            }
           
          }
          
          //// 需要刷新的元素
          if (shape._text !== cells[shape.id].value){
            const mainShape = GraphShapeUtil.getAbsoluteMainShape(shape);
            needReflowParent.add(mainShape);
            if (mainShape.getTypeName() === 'Lifeline'){
              needResizeSeqDiagram = true;

            }
            
          }
        });
        needReflowParent.forEach(mainShape => {
          ResizeUtil.updateAutoFlow(mainShape);
        });
        needResizeSeqDiagram && LifelineUtil.updateAll(graph.diagramNode.umlDiagramFrame);

        //// 如果cell没有对应的umlShape则移除cell,
        const removeCells = modelCells.filter(cell => !flatShapes.find(shape => shape.id === cell.id) && cell.id !== '0' && cell.id !== '1');
        graphUtil.deleteCellByIds(graph, removeCells.map(c => c.id));

        //// 递归差异对比，更新所有cell
        graphUtil.updateCellsByUmlShapes(graph, [diagramShape], true);
        //// const edges = modelCells.filter(cell => cell.edge);
        //// this.freshEdgeLabelPosition(graph, edges,);
        if (graph.diagramNode.getTypeName() === 'SysMLSequenceDiagram'){
          needReOrderParent.forEach(id => {
            if (graph.model.cells[id]) {
              const childs = graph.model.cells[id].children;
              const orderedCells = shapeApi.sortBySize(childs);
              graph.orderCells(false, orderedCells);
  
            }
  
          });

        }

      }
      else if (shapeId) {
        this.freshGraphByShapeId(graph, shapeId);

      } else if (shapeIds) {
        const uniqShapeIds = uniqueArr(shapeIds);
        uniqShapeIds.forEach(id => {
          this.freshGraphByShapeId(graph, id);
        });
      }
      console.timeEnd('fresh-time');
    } finally {
      graph.inFresh = false;
    }
  },

  freshGraphByShapeId(graph:Graph, id:string) {
    graphUtil.updateCellByUmlShape(graph, graph.model.cells[id].umlShape);

  },
  //// 模型更新引起图形更新 ,  如果是当前的diagram更新需要刷新diagram名字，
  //// position是edgeLabel或movableLabel的元素，如果text为空则不显示

  getFlatShapes(umlShapes: UmlShape[], flatArr: UmlShape[] = [], deep = 0): UmlShape[] {
    if (!Array.isArray(umlShapes)) {
      umlShapes = [umlShapes];
    }
    umlShapes.forEach(shape => {
      if (!shape.box.isVisible) return;
      shape._text = shape.text;
      if (shape.box.position === 'edgeLabel' || shape.box.position === 'movableLabel'){

        if (!shape._text) {
          shape.box.frontHidden = true;
          return;
        } else {
          shape.box.frontHidden = false;
        }

      }
      flatArr.push(shape);
      if (!shape.bounds){ //// 如果没有bounds说明没有初始化，是后端自动生成的图形
        const mainShape =  graphUtil.getFirstNotInitMainShape(shape);
        if (mainShape){
          ResizeUtil.initShape(mainShape);
          ResizeUtil.updateAutoFlow(mainShape);
          ResizeUtil.expandParentSize(mainShape);

        }

      }
      shape.deep = deep;
      //// if (edgeApi.isEdgeShape(shape)) return;
      const chidShapes = shape.btnShapes ? [...shape.children, ...shape.btnShapes] : shape.children;
      shape._cachedChildren = chidShapes;
      //// shape._text = shape.text;

      if (chidShapes && chidShapes.length) {
        this.getFlatShapes(chidShapes, flatArr, deep + 1);
      }
    });
    return flatArr;

  },

  updateDiagramName(graph:Graph) {
    const diagramNode = graph.diagramNode;

    const daigramShape = diagramNode.umlDiagramFrame;
    if (!daigramShape) {
      console.log('not found diagram shape');
      return;

    }
    daigramShape.text = diagramNode.getHeadDisplayName();
    const width: number = graphUtil.getTextWidth(daigramShape.text, daigramShape.box.style);
    const style: any = getStyleObj(daigramShape.box.style);
    style.width = +width + 30;
    const styleStr = getStyleStr(style);
    daigramShape.box.style = styleStr;
  },
};
